package com.allenyuan.gcode;

class gcode_parse_pair
{
	public int op;
	public int value;
}

class gcode_parse_get_first_op_result
{
	
	public int op;
	public int step;
	
	public gcode_parse_get_first_op_result(int op, int step) {
		this.op = op;
		this.step = step;
	}
}

class gcode_parse_get_first_value_result
{
	
	public int value;
	public int step;
	
	public gcode_parse_get_first_value_result(int value, int step) {
		this.value = value;
		this.step = step;
	}
}


public class GCodeParser {
	
	// private static final int GCODE_PARSE_OP_VALID = -1;
	private static final int GCODE_PARSE_OP_G = 0;
	private static final int GCODE_PARSE_OP_M = 1;

	private static final int GCODE_PARSE_OP_X = 2;
	private static final int GCODE_PARSE_OP_Y = 3;
	private static final int GCODE_PARSE_OP_F = 4;
	private static final int GCODE_PARSE_OP_R = 5;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(gcode_parse_line("G01 X10 Y100 F100"));
	}
	
	public static gcode_parse_get_first_op_result gcode_parse_get_first_op(String data, int length, int offset)
	{
		int i = 0;
		for (i = offset; i < length; ++i) {
			switch (data.charAt(i))
			{
			case 'G':
			case 'g':
				return new gcode_parse_get_first_op_result(GCODE_PARSE_OP_G, i + 1 - offset);
			case 'M':
			case 'm':
				return new gcode_parse_get_first_op_result(GCODE_PARSE_OP_M, i + 1 - offset);
			case 'X':
			case 'x':
				return new gcode_parse_get_first_op_result(GCODE_PARSE_OP_X, i + 1 - offset);
			case 'Y':
			case 'y':
				return new gcode_parse_get_first_op_result(GCODE_PARSE_OP_Y, i + 1 - offset);
			case 'F':
			case 'f':
				return new gcode_parse_get_first_op_result(GCODE_PARSE_OP_F, i + 1 - offset);
			case 'R':
			case 'r':
				return new gcode_parse_get_first_op_result(GCODE_PARSE_OP_R, i + 1 - offset);
			case ' ':
			case '\n':
				continue;
			default:
				return null;
			}
		}
		return null;
	}

	public static gcode_parse_get_first_value_result gcode_parse_get_first_value(String data, int length, int offset)
	{
		int i = 0;
		int value = 0;
		for (i = offset; i < length; ++i) {
			if (!(data.charAt(i) >= '0' && data.charAt(i) <= '9'))
			{
				break;
			}
			value *= 10;
			value += data.charAt(i) - '0';
		}
		return new gcode_parse_get_first_value_result(value, i - offset);
	}

	public static int gcode_parse_pair(gcode_parse_pair[] pairs, int length)
	{
		if (length == 0)
		{
			return -1;
		}
		switch (pairs[0].op)
		{
		case GCODE_PARSE_OP_G:
			switch (pairs[0].value)
			{
			case 0:
				if (length == 3 && pairs[1].op == GCODE_PARSE_OP_X && pairs[2].op == GCODE_PARSE_OP_Y)
				{
					System.out.print("[gcode] G00 hit\n");
					return 0;
				}
				break;
			case 1:
				if (length == 4 && pairs[1].op == GCODE_PARSE_OP_X && pairs[2].op == GCODE_PARSE_OP_Y && pairs[3].op == GCODE_PARSE_OP_F)
				{
					System.out.print("[gcode] G01 hit\n");
					return 0;
				}
				break;
			case 2:
				if (length == 5 && pairs[1].op == GCODE_PARSE_OP_X && pairs[2].op == GCODE_PARSE_OP_Y && pairs[3].op == GCODE_PARSE_OP_R && pairs[4].op == GCODE_PARSE_OP_F)
				{
					System.out.print("[gcode] G02 hit\n");
					return 0;
				}
				break;
			case 3:
				if (length == 5 && pairs[1].op == GCODE_PARSE_OP_X && pairs[2].op == GCODE_PARSE_OP_Y && pairs[3].op == GCODE_PARSE_OP_R && pairs[4].op == GCODE_PARSE_OP_F)
				{
					System.out.print("[gcode] G03 hit\n");
					return 0;
				}
				break;
			default:
				break;
			}
			break;
		case GCODE_PARSE_OP_M:
			switch (pairs[0].value)
			{
			case 3:
				if (length == 1)
				{
					System.out.print("[gcode] M03 hit\n");
					return 0;
				}
				break;
			case 5:
				if (length == 1)
				{
					System.out.print("[gcode] M05 hit\n");
					return 0;
				}
				break;
			default:
				break;
			}
			break;
		default:
			break;
		}
		return -1;
	}

	public static int gcode_parse_line(String line)
	{
		int length = line.length();
		int current_index = 0;

		int pair_num = 0;
		gcode_parse_pair[] gcode_parse_pairs = new gcode_parse_pair[5];
		for (int i = 0; i < gcode_parse_pairs.length; ++i) {
			gcode_parse_pairs[i] = new gcode_parse_pair();
		}

		while (current_index < length)
		{
			//get op
			gcode_parse_get_first_op_result op_result = gcode_parse_get_first_op(line, length, current_index);
			if (op_result == null)
			{
				System.out.print("[gcode] gcode_parse_get_first_op failed\n");
				return -1;
			}

			gcode_parse_pairs[pair_num].op = op_result.op;

			current_index += op_result.step;

			if (current_index >= length)
			{
				return -1;
			}

			//get value
			gcode_parse_get_first_value_result value_result = gcode_parse_get_first_value(line, length, current_index);
			
			if (value_result == null)
			{
				System.out.print("[gcode] gcode_parse_get_first_value failed\n");
				return -1;
			}

			gcode_parse_pairs[pair_num].value = value_result.value;

			current_index += value_result.step;

			pair_num++;
		}
	
		return gcode_parse_pair(gcode_parse_pairs, pair_num);
	}
}
